// const DAYS_IN_MONTH: [u8; 13] = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
const DAYS_BEFORE_MONTH: [u16; 13] = [0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
const SPRING_FESTIVAL: [u32; 201] = [
    0x76c011f, 0x76d0213, 0x76e0208, 0x76f011d, 0x7700210, 0x7710204, 0x7720119, 0x773020d,
    0x7740204, 0x7750116, //1900-1909
    0x776020a, 0x777011e, 0x7780212, 0x7790206, 0x77a011a, 0x77b020e, 0x77c0204, 0x77d0117,
    0x77e020b, 0x77f0201, //1910-1919
    0x7800214, 0x7810208, 0x782011c, 0x7830210, 0x7840205, 0x7850118, 0x786020d, 0x7870202,
    0x7880117, 0x789020a, //1920-1929
    0x78a011e, 0x78b0211, 0x78c0206, 0x78d011a, 0x78e020e, 0x78f0204, 0x7900118, 0x791020b,
    0x792011f, 0x7930213, //1930-1939
    0x7940208, 0x795011b, 0x796020f, 0x7970205, 0x7980119, 0x799021d, 0x79a0202, 0x79b0116,
    0x79c020a, 0x79d011d, //1940-1949
    0x79e0211, 0x79f0206, 0x7a0011b, 0x7a1020e, 0x7a20203, 0x7a30118, 0x7a4020c, 0x7a5011f,
    0x7a60212, 0x7a70208, //1950-1959
    0x7a8011c, 0x7a9020f, 0x7aa0205, 0x7ab0119, 0x7ac020d, 0x7ad0202, 0x7ae0115, 0x7af0209,
    0x7b0011e, 0x7b10211, //1960-1969
    0x7b20206, 0x7b3011a, 0x7b4020f, 0x7b50203, 0x7b60117, 0x7b7020b, 0x7b8011f, 0x7b90212,
    0x7ba0207, 0x7bb011c, //1970-1979
    0x7bc0210, 0x7bd0205, 0x7be0119, 0x7bf020d, 0x7c00202, 0x7c10214, 0x7c20209, 0x7c3011d,
    0x7c40211, 0x7c50206, //1980-1989
    0x7c6011b, 0x7c7020f, 0x7c80204, 0x7c90117, 0x7ca020a, 0x7cb011f, 0x7cc0213, 0x7cd0207,
    0x7ce011c, 0x7cf0210, //1990-1999
    0x7d00205, 0x7d10118, 0x7d2021c, 0x7d30201, 0x7d40116, 0x7d50209, 0x7d6011d, 0x7d70212,
    0x7d80207, 0x7d9011a, //2000-2009
    0x7da020e, 0x7db0203, 0x7dc0117, 0x7dd020a, 0x7de011f, 0x7df0213, 0x7e00208, 0x7e1010c,
    0x7e20210, 0x7e30205, //2010-2019
    0x7e40119, 0x7e5020c, 0x7e60201, 0x7e70116, 0x7e8020a, 0x7e9011d, 0x7ea0211, 0x7eb0206,
    0x7ec011a, 0x7ed020d, //2020-2029
    0x7ee0203, 0x7ef0117, 0x7f0020b, 0x7f1011f, 0x7f20213, 0x7f30208, 0x7f4011c, 0x7f5020f,
    0x7f60204, 0x7f70118, //2030-2039
    0x7f8020c, 0x7f90201, 0x7fa0116, 0x7fb020a, 0x7fc011e, 0x7fd0211, 0x7fe0206, 0x7ff010a,
    0x800020e, 0x8010202, //2040-2049
    0x8020117, 0x803020b, 0x8040201, 0x8050213, 0x8060208, 0x807011c, 0x808020f, 0x8090204,
    0x80a0118, 0x80b020c, //2050-2059
    0x80c0202, 0x80d0115, 0x80e0209, 0x80f011d, 0x8100211, 0x8110205, 0x812011a, 0x813020e,
    0x8140203, 0x8150117, //2060-2069
    0x816020b, 0x817011f, 0x8180213, 0x8190207, 0x81a011b, 0x81b020e, 0x81c0205, 0x81d0118,
    0x81e020c, 0x81f0202, //2070-2079
    0x8200116, 0x8210209, 0x822011d, 0x8230211, 0x8240206, 0x825011a, 0x826021e, 0x8270203,
    0x8280118, 0x829020a, //2080-2089
    0x82a011e, 0x82b0212, 0x82c0207, 0x82d011b, 0x82e020f, 0x82f0205, 0x8300109, 0x831020c,
    0x8320201, 0x8330115, //2090-2099
    0x8340209, //2100
];

/// 是否闰年
fn is_leap(year: u16) -> bool {
    year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)
}

/// 从 0000-01-01 开始到 {year}-01-01 的天数
fn days_before_year(year: u16) -> u32 {
    let y = year as u32 - 1;
    y * 365 + y / 4 - y / 100 + y / 400
}

// /// 当前月份天数
// fn days_in_month(year: u16, month: u8) -> u8{
//     if month == 2 && is_leap(year){
//         29
//     }else{
//         DAYS_IN_MONTH[month as usize]
//     }
// }

/// 从 {year}-01-01 开始到 {year}-{month} 月底的天数
fn days_before_month(year: u16, month: u8) -> u32 {
    DAYS_BEFORE_MONTH[month as usize] as u32 + if month > 2 && is_leap(year) { 1 } else { 0 }
}

/// 从 0000-01-01 开始到 当前日期 的天数
fn ymd_to_ord(year: u16, month: u8, day: u8) -> u32 {
    days_before_year(year) + days_before_month(year, month) + day as u32
}

fn iso_week1monday(year: u16) -> u32 {
    let firstday = ymd_to_ord(year, 1, 1) as i32;
    let firstweekday = (firstday + 6) % 7;
    let week1monday = firstday - firstweekday;
    if firstweekday > 3 {
        (week1monday + 7) as u32
    } else {
        week1monday as u32
    }
}

fn get_week(year: u16, month: u8, day: u8) -> u32 {
    let week1monday = iso_week1monday(year);
    let today = ymd_to_ord(year, month, day);

    if today < week1monday {
        ((today - iso_week1monday(year - 1)) / 7) + 1
    } else {
        let week = (today - week1monday) / 7;
        if week >= 52 && today >= iso_week1monday(year + 1) {
            1
        } else {
            week + 1
        }
    }
}

struct Ymd {
    year: u16,
    month: u8,
    day: u8,
}

impl TryFrom<&str> for Ymd {
    type Error = &'static str;

    fn try_from(value: &str) -> Result<Self, Self::Error> {
        let v = value.split("-").collect::<Vec<&str>>();
        if v.len() != 3 {
            return Err("date format error");
        }

        Ok(Ymd {
            year: v[0].parse::<u16>().map_err(|_| "year fromat error")?,
            month: v[1].parse::<u8>().map_err(|_| "month fromat error")?,
            day: v[2].parse::<u8>().map_err(|_| "day fromat error")?,
        })
    }
}

fn spring_festival(year: u16) -> u32 {
    let sp = SPRING_FESTIVAL[year as usize - 1900];
    ymd_to_ord(
        (sp >> 16) as u16,
        ((sp >> 8) & 0xff) as u8,
        (sp & 0xff) as u8,
    )
}
pub fn time_info(time: &str) -> String {
    if let Ok(ymd) = Ymd::try_from(time) {
        let week = get_week(ymd.year, ymd.month, ymd.day);
        let ord = ymd_to_ord(ymd.year, ymd.month, ymd.day);
        let next_year = ymd_to_ord(ymd.year + 1, 1, 1);
        let mut sf = spring_festival(ymd.year);
        if sf < ord {
            sf = spring_festival(ymd.year + 1);
        }

        format!("{},{},{}", week, next_year - 1 - ord, sf - ord - 1)
    } else {
        String::new()
    }
}
